package common

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"

	sdk "github.com/Conflux-Chain/go-conflux-sdk"
	"github.com/ethereum/go-ethereum/accounts/keystore"
)

// 支持多种以太坊链，如ETH, BSC等
type ChainInfo struct {
	ChainId      int      `json:"chainId"`      // 链id mainnet:1 ropsten:3 bsc:56 bsc testnet:97 等等
	NodeUrl      string   `json:"nodeUrl"`      // 访问该链地址，可以是本地建立节点后提供的访问地址，也可使用第三方提供访问地址如infura.io
	NodeWssPath  string   `json:"nodeWssPath"`  // wss地址，用于接收合约事件通知
	WatchAddress []string `json:"watchAddress"` // wss接收具体合约上（可多个合约）事件通知
}

type NftConf struct {
	ServerName     string               `json:"serverName"`       // 服务名称
	RunEnv         string               `json:"runEnv,omitempty"` // 当前运行环境 test: 测试 prod: 正式环境
	ServerAddr     int                  `json:"serverAddr"`       // 服务监听ip端口
	LogLevel       int                  `json:"logLevel"`         // 日志级别
	SignRandomKey  string               `json:"signRandomKey"`    // http访问加密串
	PassWord       string               `json:"passWord"`         // 本地钱包密码（重要，请勿泄露！）
	KeystorePath   string               `json:"keystorePath"`     // 本地钱包保存路径
	PrivateKey     string               `json:"privateKey"`       // 私钥
	SupportChains  map[string]ChainInfo `json:"supportChains"`    // 合约支持链信息
	NotifyHttpPath string               `json:"notifyHttpPath"`   // 合约事件通知（如未配置则不通知）
	IpfsNodePath   string               `json:"ipfsNodePath"`     // NFT实际内容上传到ipfs的访问路径（如未配置则不上传）
	LocalWallet    *keystore.KeyStore   `json:"-"`                // ETH 本地钱包中所有账户
	AccountManager *sdk.AccountManager  `json:"-"`                // CFX 本地钱包中所有账户 AccountManager
	CfxClient      *sdk.Client          `json:"-"`                // CfxClient
	JwtSecret      string               `json:"jwtSecret"`        // jwt加密串
	IsLoaded       bool                 `json:"-"`                // 是否已经加载配置
}

var GlobalConf NftConf

func LoadConfig(file string) error {
	buf, err := ioutil.ReadFile(file)
	if err != nil {
		fmt.Println("Read config file failed!")
		return err
	}
	err = json.Unmarshal(buf, &GlobalConf)
	if err != nil {
		fmt.Println("Decode config file failed!")
		return err
	}
	// 创建cfx client
	if GlobalConf.RunEnv == "test" {
		GlobalConf.CfxClient, err = sdk.NewClient(GlobalConf.SupportChains["cfx_test"].NodeUrl, sdk.ClientOption{
			KeystorePath: GlobalConf.KeystorePath,
		})
	} else {
		GlobalConf.CfxClient, err = sdk.NewClient(GlobalConf.SupportChains["cfx"].NodeUrl, sdk.ClientOption{
			KeystorePath: GlobalConf.KeystorePath,
		})
	}
	if err != nil {
		fmt.Println(err)
	}

	// _, err := GlobalConf.CfxClient.GetEpochNumber()
	// if err != nil {
	// 	fmt.Println(err)
	// }
	chainID, err := GlobalConf.CfxClient.GetNetworkID()
	if err != nil {
		fmt.Println(err)
	}

	// 加载钱包中账户
	if len(GlobalConf.KeystorePath) <= 0 {
		return errors.New("Not set wallet path!")
	}
	//ETH
	GlobalConf.LocalWallet = keystore.NewKeyStore(GlobalConf.KeystorePath, keystore.StandardScryptN, keystore.StandardScryptP)
	//CFX
	GlobalConf.AccountManager = sdk.NewAccountManager(GlobalConf.KeystorePath, chainID)

	address, err := GlobalConf.AccountManager.ImportKey(GlobalConf.PrivateKey, GlobalConf.PassWord)
	fmt.Println("address:", address)
	if err != nil {
		fmt.Println("Cfx Import to keystore failed!", err)
		// return err
	}

	GlobalConf.CfxClient.SetAccountManager(GlobalConf.AccountManager)

	// 重置配置文件中钱包密码信息，防止密码泄露！
	if GlobalConf.RunEnv == "prod" {
		// tmpConf := GlobalConf
		// tmpConf.PassWord = ""
		// buf, err = json.Marshal(tmpConf)
		// err = ioutil.WriteFile(file, buf, 0600)
		// if err != nil {
		// 	fmt.Println("Rewrite config file failed!")
		// }
	}
	GlobalConf.IsLoaded = true
	return nil
}
